<?php

namespace App\Helpers;

/*
 * 解析请求参数
 *
    {
        "sort":[
            {
                "selector":"id",
                "desc":true
            }
        ],
        "group":null,
        "requireTotalCount":true,
        "searchOperation":"contains",
        "searchValue":"13",
        "searchExpr":"mobile",
        "skip":0,
        "take":10,
        "userData":{

        },
        "filter":[
            "status",
            "=",
            1
        ]
    }
 *
 */

trait ApiListTrait
{
    //排序
    protected $sort;

    //分组
    protected $group;

    //总数
    protected $requireTotalCount;

    //搜索
    protected $searchOperation;

    //搜索的值
    protected $searchValue;

    //搜索的字段
    protected $searchExpr;

    //起始
    protected $skip=0;

    //长度
    protected $take=0;

    //过滤
    protected $filter;

    protected $processQueryModel;

    public $totalCount = 0;

    public $params;

    public function build($query,$params=null)
    {
        $this->processQueryModel = $query;

        $this->params = $params;

        $params = json_decode($params,true);

        $this->assignment($params);

        return $this;
    }

    //赋值
    protected function assignment($params)
    {
        $vars = ['sort','group','requireTotalCount','searchOperation','searchValue','searchExpr',
            'skip','take','filter'];
        foreach ($vars as $v){
            if(isset($params[$v]) && $params[$v]){
                $this->$v = $params[$v];
            }
        }
        return $this;
    }


    //获取结果集
    protected function getListItems()
    {

        $this->processFilter();//过滤

        $this->processSearch();//搜索

        $this->processSort();//过滤

        $this->processPages();//分页

        $this->processQueryModel = $this->beforeListShow($this->processQueryModel);


        $items = $this->getResultItems($this->processQueryModel);

        if($loads = $this->relationLoad()) {
            $items->load($loads);
        }

        return $items;
    }

    protected function getResultItems($query)
    {
        return $query->get();
    }

    protected function getSimpleListItems()
    {
        $this->processFilter();//过滤

        $this->processSearch();//搜索

        $this->processSort();//过滤

        $this->processPages();//分页

        $this->processQueryModel = $this->beforeListShow($this->processQueryModel);

        $simpleListFiled = $this->simpleListFiled();

        if (count($simpleListFiled)>0){
            $items = $this->processQueryModel->select($simpleListFiled)->get();
            return $items;
        }

        $items = $this->processQueryModel->get();
        return $items;
    }

    //在列表显示之前
    protected function beforeListShow($model)
    {
        return $model->orderBy('created_at','desc');
    }

    //加载关联
    protected function relationLoad()
    {
        return [];
    }

    //过滤
    protected function processFilter()
    {
        $query = $this->processQueryModel;

        $filter = $this->filter;

        if (!$filter) return $query;

        $filters = [];

        if (is_array($filter)) {
            foreach ($filter as $k=>$v){
                if (is_array($v) && count($v)==3){
                    $filters[] = $v;
                }elseif((is_string($v) ||is_numeric($v)) && count($filter) == 3){
                    $filters[] = $filter;
                    break;
                }
            }
        }

        foreach ($filters as $filter) {
            if(strpos($filter[0],'.') === false && in_array($filter[0],$this->modelColumns())) {
                $query = $query->where($filter[0],$filter[1],$filter[2]);
            }else{
                $query = $this->processRelationFilter($query,$filter[0],$filter[1],$filter[2]);
            }
        }
        $this->processQueryModel = $query;

        return $query;
    }

    //关联过滤
    protected function processRelationFilter($query,$key,$operator ,$value)
    {
        return $query;
    }

    //搜索
    protected function processSearch()
    {
        $query = $this->processQueryModel;

        if(!($this->searchValue && $this->searchExpr && $this->searchOperation)){
            return $query;
        }

        $columns = $this->modelColumns();


        if(is_string($this->searchExpr)) {
            $this->searchExpr = explode(',',$this->searchExpr);
        }

        $sql = [];
        $relationSql = [];

        foreach ($this->searchExpr as $search){
            if(in_array($search,$columns)) {
                $sql[] = '`'.$search.'` like "%'.$this->searchValue.'%"';
            } elseif($relSql = $this->processRelationSearch($search, $this->searchValue)) {
                $relationSql[] = $relSql;
            }
        }

        $sql1 = implode('OR',$sql);
        $sql2 = implode('OR',$relationSql);

        $query = $query->whereRaw('('.($sql1?$sql1:1).')')->whereRaw('('.($sql2?$sql2:1).')');

        $this->processQueryModel = $query;

        return $query;
    }

    //关联搜索
    protected function processRelationSearch($key,$value)
    {
        return false;
    }

    //排序
    protected function processSort()
    {
        $query = $this->processQueryModel;

        if ($this->sort && count($this->sort) > 0) {
            foreach ($this->sort as $sort) {
                if ($sort['selector'] && in_array($sort['selector'],$this->modelColumns())) {
                    $query = $query->orderBy($sort['selector'], $sort['desc'] ? 'desc' : 'asc');
                }else{
                    $query = $this->processRelationSort($sort['selector'],$sort['desc'] ? 'desc' : 'asc');
                }
            }
        }

        $this->processQueryModel = $query;

        return $query;

    }

    //关联排序
    protected function processRelationSort($key,$sort)
    {
        return $this->processQueryModel;
    }

    //分页
    protected function processPages()
    {
        $query = $this->processQueryModel;

        $this->totalCount = $query->count();

        if($this->skip >=0 && $this->take>0) {

            $query = $query->skip($this->skip)->take($this->take);
        }

        $this->processQueryModel = $query;


        return $query;
    }

}
